#pragma once

#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>

template <typename T>
class RingQueue
{

private:
    // 定义队列信息
    int _cap;
    std::vector<T> _ring_queue;

    // 定义各自下标
    int _consumer_step;
    int _productor_step;

    // 定义信号量
    sem_t _room_sem;
    sem_t _data_sem;

    // 定义2个锁
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;

private:
    void P(sem_t &sem)
    {
        sem_wait(&sem); // 内核进行--操作
    }
    void V(sem_t &sem)
    {
        sem_post(&sem); // 内核会进行++操作
    }

public:
    RingQueue(int cap) : _cap(cap), _ring_queue(cap),
                         _consumer_step(0),
                         _productor_step(0) // 这里是n哦 稍等以下 看错了
    {
        sem_init(&_room_sem, 0, _cap);
        sem_init(&_data_sem, 0, 0);

        pthread_mutex_init(&_productor_mutex, nullptr);
        pthread_mutex_init(&_consumer_mutex, nullptr);
    };

    void Lock(pthread_mutex_t &mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void unLock(pthread_mutex_t &mutex)
    {
        pthread_mutex_unlock(&mutex);
    }

    void Enqueue(const T &in)
    {

        P(_room_sem); // P操作申请空间
        Lock(_productor_mutex);
        _ring_queue[_productor_step++] = in; // 直接生产
        _productor_step %= _cap;

        V(_data_sem); // 对数据V操作。
        unLock(_productor_mutex);
    }
    void Pop(T *out)
    {

        P(_data_sem); // 申请数据资源
        Lock(_consumer_mutex);
        *out = _ring_queue[_consumer_step++];
        // _ring_queue.erase(_consumer_step);
        // ring_queue[_consumer_step++]
        _consumer_step %= _cap;
        V(_room_sem); // 对空间V操作
        unLock(_consumer_mutex);
    }
    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);

        pthread_mutex_destroy(&_productor_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    };
};